#include "app_uart.h"
#include <string.h>
#include "crc16.h"
extern volatile int32_t DRV_PWMCOUNT;
#include "app_uart_drv.h"

/***************************************************************************************************
 * variable definition
 **************************************************************************************************/


#define INST_UART_BLE       (1)
                           
#define UART_BLE_RX_SIZE    10
                         
uint8_t g_RecData[UART_BLE_RX_SIZE];
volatile bool g_rxComplete = false;
volatile bool g_txComplete = false;

// 协议常量定义
#define FRAME_HEADER_0  0x5A
#define FRAME_HEADER_1  0xA5            
#define CMD_MCU_DOWN    0x82 // MCU下发
#define CMD_SCREEN_UP   0x83 // 手机上传

uint16_t aimUpperRPM;    // 0–100    实际转速 = 2000 + 60 * aimUpperRPM
uint16_t aimBelowRPM;    // 0–100
uint16_t aimPitchAngle;  // 0–90
uint16_t aimYawAngle;    // 0–90
uint16_t aimBallRPM;     // 0–100
uint16_t stateInfo;


uint16_t aimUpperRPM;
uint16_t aimBelowRPM;
uint16_t aimPitchAngle;
uint16_t aimYawAngle; 
uint16_t aimBallRPM;

uint8_t frame[5];

/***************************************************************************************************
 * function declaration
 **************************************************************************************************/

/* Uart rx callback function */
void Uart01_RxCallback(void *LINFLexDState, uart_event_t event, void *userData);

/* Uart tx callback function */
void Uart01_TxCallback(void *LINFLexDState, uart_event_t event, void *userData);

/***************************************************************************************************
 * Scheduling function definition
 ***************************************************************************************************/

 void app_uartInit() {
    
    LINFlexD_UART_DRV_Init(INST_UART_BLE,&linflexd_uart_config0_State,&linflexd_uart_config0);
 
//    LINFlexD1->LINCR1 |= LINFlexD_LINCR1_INIT(1);  
//    LINFlexD1->GCR |= LINFlexD_GCR_RDLIS(1);
//    LINFlexD1->GCR |= LINFlexD_GCR_TDLIS(1);  
//    LINFlexD1->LINCR1 &= ~LINFlexD_LINCR1_INIT(1); 
    
    LINFlexD_UART_DRV_InstallRxCallback(INST_UART_BLE, Uart01_RxCallback, NULL);
    LINFlexD_UART_DRV_InstallTxCallback(INST_UART_BLE, Uart01_TxCallback, NULL);
     
     
    INT_SYS_EnableIRQ(LINFlexD0_IRQn);

    /* Send received data */
    LINFlexD_UART_DRV_ReceiveData(INST_UART_BLE, g_RecData, UART_BLE_RX_SIZE);
}

// ====================== 报文发送函数 ======================
// 通用帧构造函数
static void build_frame(uint8_t *buf, uint8_t cmd) {
    buf[0] = FRAME_HEADER_0;
    buf[1] = FRAME_HEADER_1;
    buf[2] = CMD_MCU_DOWN;
    buf[3] = cmd;
    buf[4] = crc_16(buf, 4);
}                                  

void app_sendReceivedInfo() {
   
    build_frame(frame, 1);
    
    LINFlexD_UART_DRV_SendData(INST_UART_BLE, frame, 5);    //  5A A5 82 01 A3
    
}

void app_sendFinishInfo() {
    
    build_frame(frame, 2);
    LINFlexD_UART_DRV_SendData(INST_UART_BLE, frame, 5);
}

void app_sendRejectInfo() {
    
    build_frame(frame, 0);
    LINFlexD_UART_DRV_SendData(INST_UART_BLE, frame, 5);
}

// ====================== 报文解析函数 ======================
void app_uartReceiveData() {
    
    if (!g_rxComplete)
        return;
    
    g_rxComplete = false;
    LINFlexD_UART_DRV_ReceiveData(INST_UART_BLE, g_RecData, UART_BLE_RX_SIZE);
    
    // 进行解析    
    uint8_t length = sizeof(g_RecData) / sizeof(g_RecData[0]);
    
    if (length < UART_BLE_RX_SIZE)
        return;
    
    if (g_RecData[0]!=FRAME_HEADER_0 || g_RecData[1]!=FRAME_HEADER_1 
        || g_RecData[2]!=CMD_SCREEN_UP)
        return;
    
    if (crc_16(g_RecData, UART_BLE_RX_SIZE-1)!=g_RecData[UART_BLE_RX_SIZE-1])
        return;

    aimUpperRPM = g_RecData[3];     
    aimBelowRPM = g_RecData[4];     
    aimPitchAngle = g_RecData[5];   
    aimYawAngle = g_RecData[6];     
    aimBallRPM = g_RecData[7];     
    stateInfo = g_RecData[8];      
    
    if (aimUpperRPM > 100 || aimBelowRPM > 100 ||
        aimPitchAngle > 90 || aimYawAngle > 90 ||
        aimBallRPM > 100 ) {  // 拒绝执行
        app_sendRejectInfo(); 
        
    } else { // 接受
        app_sendReceivedInfo();     

        // deal with data 
        
        // 上下电机目标速度
        if (aimUpperRPM == 0) { // 停止
            app_uartDrvSendStopInfo(INST_UART_DRV1);
        } else {
            app_uartDrvSendSpeedInfo(INST_UART_DRV1, 2000 + aimUpperRPM * 60);
        }
        
        if (aimBelowRPM == 0) {
            app_uartDrvSendStopInfo(INST_UART_DRV2);
            
        } else  {
            app_uartDrvSendSpeedInfo(INST_UART_DRV2, 2000 + aimBelowRPM * 60);
        }
        
        // TODO: 角度
        
        // 已轮询 extern aimPitchAngle aimYawAngle 值
        
        // TODO: 拨球电机速度
				if (aimBallRPM == 0) {
        eTMR3->CH[0].VAL0 = DRV_PWMCOUNT / 2;
        eTMR3->CH[0].VAL1 = DRV_PWMCOUNT / 2;
				} else {
        uint16_t duty = (DRV_PWMCOUNT * aimBallRPM) / 100;
        eTMR3->CH[0].VAL0 = (DRV_PWMCOUNT >> 1) - (duty >> 1);
        eTMR3->CH[0].VAL1 = (DRV_PWMCOUNT >> 1) + (duty >> 1);
        eTMR3->SYNC &= ~eTMR_SYNC_LDOK_MASK;
        eTMR3->SYNC |= eTMR_SYNC_LDOK_MASK;
				}  
    }

}
 
 /* Uart rx callback function */
void Uart01_RxCallback(void *LINFLexDState, uart_event_t event, void *userData)
{
    (void)LINFLexDState;
    (void)userData;
    if (event == UART_EVENT_END_TRANSFER)
    {
        g_rxComplete = true;
    }
}

/* Uart tx callback function */
void Uart01_TxCallback(void *LINFLexDState, uart_event_t event, void *userData)
{
    (void)LINFLexDState;
    (void)userData;
    if (event == UART_EVENT_END_TRANSFER)
    {
        g_txComplete = true;                
//        PINS_DRV_SetMuxModeSel(PCTRLC, 9, PCTRL_MUX_AS_GPIO);   
//        PINS_DRV_SetPins(GPIOC, 1<<9);
    }
}
 


